File: AbstractAllocationAnalyzer`1.cs
Web Access
Project: src\src\RoslynAnalyzers\PerformanceSensitiveAnalyzers\Core\Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers.csproj (Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Collections.Immutable;
using Analyzer.Utilities.Extensions;
using Microsoft.CodeAnalysis.Diagnostics;
 
namespace Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers
{
    internal abstract class AbstractAllocationAnalyzer<TLanguageKindEnum>
            : AbstractAllocationAnalyzer
            where TLanguageKindEnum : struct
    {
        protected abstract ImmutableArray<TLanguageKindEnum> Expressions { get; }
 
        protected sealed override ImmutableArray<OperationKind> Operations => ImmutableArray<OperationKind>.Empty;
 
        protected abstract void AnalyzeNode(SyntaxNodeAnalysisContext context, in PerformanceSensitiveInfo info);
 
        protected override void AnalyzeNode(OperationAnalysisContext context, in PerformanceSensitiveInfo info) { }
 
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();
 
            // This analyzer is triggered by an attribute, even if it appears in generated code
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
 
            context.RegisterCompilationStartAction(compilationStartContext =>
            {
                var compilation = compilationStartContext.Compilation;
                var attributeSymbol = compilation.GetOrCreateTypeByMetadataName(AllocationRules.PerformanceSensitiveAttributeName);
 
                // Bail if PerformanceSensitiveAttribute is not declared in the compilation.
                if (attributeSymbol == null)
                {
                    return;
                }
 
                compilationStartContext.RegisterCodeBlockStartAction<TLanguageKindEnum>(blockStartContext =>
                {
                    var checker = new AttributeChecker(attributeSymbol);
                    RegisterSyntaxAnalysis(blockStartContext, checker);
                });
            });
        }
 
        private void RegisterSyntaxAnalysis(CodeBlockStartAnalysisContext<TLanguageKindEnum> codeBlockStartAnalysisContext, AttributeChecker performanceSensitiveAttributeChecker)
        {
            var owningSymbol = codeBlockStartAnalysisContext.OwningSymbol;
 
            if (!performanceSensitiveAttributeChecker.TryGetContainsPerformanceSensitiveInfo(owningSymbol, out var info))
            {
                return;
            }
 
            codeBlockStartAnalysisContext.RegisterSyntaxNodeAction(
                syntaxNodeContext =>
                {
                    AnalyzeNode(syntaxNodeContext, in info);
                },
                Expressions);
        }
    }
}